//
// Created by alexa on 5/13/2024.
//

#include "SoldierRepository.h"

#include <fstream>
#include <nlohmann/json.hpp>

using json = nlohmann::json;

Soldier *SoldierRepository::findById(string id) {
    return source.getById(id);
}

void SoldierRepository::save(Soldier *soldier) {
    if (!source.getById(soldier->getId())) source.add(soldier);
    if (!fileSourcePath.empty()) {
        saveDataToFile();
    }
}

void SoldierRepository::deleteOne(Soldier *soldier) {
    if (source.getById(soldier->getId())) {
        source.removeById(soldier->getId());
    }
    if (!fileSourcePath.empty()) {
        saveDataToFile();
    }
}

vector<Soldier *> SoldierRepository::findAll() {
    return source.getAll();
}

void SoldierRepository::loadDataFromFile() {
    if (fileSourcePath.empty()) return;
    ifstream file(fileSourcePath);
    if (!file.good()) {
        file.close();
        return;
    }
    json data;
    try {
        data = json::parse(file);
    } catch (json::exception &pass) {
        file.close();
        return;
    }
    if (!data.is_array()) return;

    for (const auto &el: data) {
        try {
            string id = el.at("id");
            string firstname = el.at("firstname");
            string surname = el.at("surname");
            string rank = el.at("rank");
            Specialization specialization = static_cast<Specialization>(el.at("specialization"));
            Soldier *soldier = new Soldier(firstname, surname, rank, specialization);
            soldier->setId(id);
            this->source.add(soldier);
        } catch (json::exception &e) {
            continue;
        }
    }

    file.close();
}

void SoldierRepository::saveDataToFile() {
    ofstream file(fileSourcePath);

    json jarr = json::array();

    vector<Soldier *> list = findAll();

    for (const auto &el: list) {
        json jobj = json::object();
        jobj["id"] = el->getId();
        jobj["firstname"] = el->getFirstname();
        jobj["surname"] = el->getSurname();
        jobj["rank"] = el->getRank();
        jobj["specialization"] = (int) el->getSpecialization();
        jarr.push_back(jobj);
    }
    file << jarr.dump(4) << endl;
    file.close();
}

const string &SoldierRepository::getFileSourcePath() const {
    return fileSourcePath;
}

void SoldierRepository::setFileSourcePath(const string &fileSourcePath) {
    this->fileSourcePath = fileSourcePath;
    if (!fileSourcePath.empty()) {
        loadDataFromFile();
    }
}

SoldierRepository::SoldierRepository(const string &fileSourcePath) : fileSourcePath(fileSourcePath) {
    if (!fileSourcePath.empty()) {
        loadDataFromFile();
    }
}

SoldierRepository::~SoldierRepository() {
    vector<Soldier *> list = findAll();
    for (auto &el: list) {
        delete el;
    }
}
